var CANVAS_WIDTH, CANVAS_HEIGHT;
var BOARD_WIDTH, BOARD_HEIGHT;

var DELTA_X, BALL_SIZE;

var canvas, canvasTimer;
var ball, player1, player2;

var stopped = true;
var prevX;

$(document).on("click touchstart", function(event) {
    if (stopped) {
        ball.velocityX = 0;
        ball.velocityY = (Math.random() <= 0.5) ? -9 : 9;
        ball.update();

        prevX = event.originalEvent.touches[0].pageX;
        stopped = false;
    }
});

$(document).on("touchmove", function(event) {
    event.preventDefault();
    event.stopPropagation();

    if (stopped)
        return;

    var touch = event.originalEvent.touches[0];

    keydown.right = touch.pageX > prevX;
    keydown.left = !keydown.right;

    player1.update();
    player2.update();

    keydown.right = keydown.left = false;
    prevX = touch.pageX;
});

function initHTML() {
	var $canvasElement = $(".draw_area");

    var a = $canvasElement.width();
    var b = $(".wrap").height() - $(".score_block").outerHeight() -
            parseFloat($canvasElement.css("margin-top")) * 3;

    CANVAS_WIDTH = a;
    CANVAS_HEIGHT = b;

    BALL_SIZE = CANVAS_HEIGHT * 0.04;
    DELTA_X = CANVAS_WIDTH * 0.01;

    BOARD_WIDTH = CANVAS_WIDTH * 0.2;
    BOARD_HEIGHT = CANVAS_HEIGHT * 0.03;

    $canvasElement.attr("width", CANVAS_WIDTH);
    $canvasElement.attr("height", CANVAS_HEIGHT);

    canvas = $canvasElement.get(0).getContext("2d");
	$canvasElement.insertBefore('.score_block');
	canvas.backgroundColor = "lightblue";

	var FPS = 30;
	canvasTimer = setInterval(function() {
		draw();
		player1.handleCollisions().update();
		player2.handleCollisions().update();
		ball.update();
	}, 1000 / FPS);
}

function draw() {
	canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
	player1.draw();
	player2.draw();
	ball.draw();
}

function CanvasItem() {
	this.x = 0;
	this.y = 0;

	this.width = 10;
	this.height = 10;

	this.color = 'grey';
}

CanvasItem.prototype.draw = function() {
	canvas.fillStyle = this.color;
	canvas.fillRect(this.x, this.y, this.width, this.height);
};

CanvasItem.prototype.collides = function (a) {
	return this.x < a.x + a.width &&
		   this.y < a.y + a.height &&
		   this.x + this.width > a.x &&
		   this.y + this.height > a.y;
};

CanvasItem.prototype.midpoint = function() {
    return { x: this.x + this.width / 2,
             y: this.y + this.height / 2 };
};

function Player(x, y, width, height, ball) {
	this.startPositionX = this.x = x;
	this.startPositionY = this.y = y;

	this.width = width;
	this.height = height;

    this.color = 'blue';
	this.score = 0;
	this.ball = ball;
}

Player.prototype = new CanvasItem();

Player.prototype.handleCollisions = function() {
	var ball = this.ball;
	var k = this.midpoint().x / ball.midpoint().x;
	
	if (k < 1)
		k = k - 2;
	else if (k == 1)
		k = 0;
		
	if (pushFromTop(this, ball)) {
		ball.velocityY = -9;
		ball.velocityX = -2 * k;
	}
	else if (pushFromBot(this, ball)) {
		ball.velocityY = 9;
		ball.velocityX = -2 * k;
	}
	return this;
};

Player.prototype.update = function() {
	if (keydown.left)	this.x -= DELTA_X;
	if (keydown.right)	this.x += DELTA_X;

	//this.x = clamp(0, CANVAS_WIDTH - this.width);
	this.x = Math.min(this.x, CANVAS_WIDTH - this.width);
	this.y = Math.min(this.y, CANVAS_HEIGHT - this.height);
	this.x = Math.max(this.x, 0);
	this.y = Math.max(this.y, 0);
	return this;
};

Player.prototype.reset = function() {
	this.x = this.startPositionX;
	this.y = this.startPositionY;
};

function Ball(startX, startY, size) {
	this.x = startX;
	this.y = startY;
    this.width = this.height = size;

	this.velocityY = 0;
	this.velocityX = 0;

    this.color = 'red';
}

Ball.prototype = new CanvasItem();

Ball.prototype.update = function() {
	this.y += this.velocityY;
	this.x += this.velocityX;

	if (this.x > CANVAS_WIDTH - this.width || this.x < 0)
		this.velocityX = -this.velocityX;

	if (this.y > CANVAS_HEIGHT - this.height) {
		player1.score += 1;
		updateScore();

        this.reset(true);
		stopped = true;

		player1.reset();
		player2.reset();
	}
	else if (this.y < 0) {
		player2.score += 1;
		updateScore();

		this.reset(false);
        stopped = true;
		
		player1.reset();
		player2.reset();
	}
};

Ball.prototype.reset = function(isPositionBot) {
	this.x = CANVAS_WIDTH / 2;
	this.y = isPositionBot ? 460 : 40;
	this.velocityY = 0;
	this.velocityX = 0;
};

function updateScore() {
	$('.score_block').text(player1.score + ':' + player2.score);
}

function clamp(min, max) {
	return Math.min(Math.max(this, min), max);
}

function pushFromBot(a, b) {
	return a.collides(b) && (a.y < b.y);
}

function pushFromTop(a, b) {
	return a.collides(b) && (a.y > b.y);
}

$(document).ready(function() {
	initHTML();

    ball = new Ball(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, BALL_SIZE);
    player1 = new Player(CANVAS_WIDTH / 2 - BOARD_WIDTH / 2, CANVAS_HEIGHT * 0.98 - BOARD_HEIGHT,
                         BOARD_WIDTH, BOARD_HEIGHT, ball);
    player2 = new Player(CANVAS_WIDTH / 2 - BOARD_WIDTH / 2, CANVAS_HEIGHT * 0.02,
                         BOARD_WIDTH, BOARD_HEIGHT, ball);
});